CH82 -- optimization

Input: Defines the model and constraints


In [1]:
from dcprogs import read_idealized_bursts
from dcprogs.likelihood import QMatrix

name   = "CH82.scn"
tau    = 1e-4
tcrit  = 4e-3 
graph  = [["V", "V", "V",   0,   0],
          ["V", "V",   0, "V",   0],
          ["V",   0, "V", "V", "V"],
          [  0, "V", "V", "V",   0],
          [  0,   0, "V",   0, "V"]] 
nopen  = 2
qmatrix = QMatrix([[ -3050,        50,  3000,      0,    0 ], 
                  [ 2./3., -1502./3.,     0,    500,    0 ],  
                  [    15,         0, -2065,     50, 2000 ],  
                  [     0,     15000,  4000, -19000,    0 ],  
                  [     0,         0,    10,      0,  -10 ] ], 2)

bursts = read_idealized_bursts(name, tau=tau, tcrit=tcrit)

Creates the constraints, the likelihood function, as well as a function to create random Q-matrix.


In [2]:
from scipy.optimize import minimize
from numpy import NaN, zeros, arange
import numpy as np
from dcprogs.likelihood.random import qmatrix as random_qmatrix
from dcprogs.likelihood import QMatrix, Log10Likelihood
from dcprogs.likelihood.optimization import reduce_likelihood

likelihood = Log10Likelihood(bursts, nopen, tau, tcrit)
reduced = reduce_likelihood(likelihood, graph)
x = reduced.to_reduced_coords( random_qmatrix(5).matrix )

constraints = []
def create_inequality_constraints(i, value=0e0, sign=1e0):
    f = lambda x: sign * (x[i]  - value)
    def df(x):
        a = zeros(x.shape)
        a[i] = sign
        return a
    return f, df

for i in range(len(x)):
    f, df = create_inequality_constraints(i)
    constraints.append({'type': 'ineq', 'fun': f, 'jac': df})
    f, df = create_inequality_constraints(i, 1e4, -1)
    constraints.append({'type': 'ineq', 'fun': f, 'jac': df})

    
def random_starting_point():
    from numpy import infty, NaN
    from dcprogs.likelihood.random import rate_matrix as random_rate_matrix
    
     
    for i in range(100):
        matrix = random_rate_matrix(N=len(qmatrix.matrix), zeroprob=0)
        x = reduced.to_reduced_coords( matrix )
        try: 
            result = reduced(x)
            print(result, reduced.to_full_coords(x))
        except:
            pass
        else: 
            if result != NaN and result != infty and result != -infty: break
    else: raise RuntimeError("Could not create random matrix") 
    return x

def does_not_throw(x):
    try: return -reduced(x)
    except: return NaN

Performs the minimization


In [3]:
import math
methods = ['COBYLA', 'SLSQP']
x = random_starting_point()
print ('x=', x)
maxx = (x.copy(), reduced(x))
for i in range(len(methods)):
    result = minimize(does_not_throw,
                      x,
                      method=methods[i],
                      constraints=constraints,
                      options={'maxiter': 1000, 'disp':True}) 

    print(result)
    if not math.isnan(result.fun):
        if result.fun < maxx[1]: maxx = (x.copy(), result.fun)
        if result.success and i > 4: break
    x +=  random_starting_point() * 1e-2
    if np.all(np.isnan(x)): x = random_starting_point()
print(maxx[0])
print(maxx[1])


-12.425436251427712 [[ -6.44069267e+03   5.74181654e-01   6.44011849e+03   0.00000000e+00
    0.00000000e+00]
 [  1.16073652e+03  -1.16142765e+03   0.00000000e+00   6.91127353e-01
    0.00000000e+00]
 [  3.22274403e-01   0.00000000e+00  -2.90372168e+03   2.90281124e+03
    5.88161958e-01]
 [  0.00000000e+00   3.41367880e-01   7.55204456e-01  -1.09657234e+00
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   5.08084841e-01   0.00000000e+00
   -5.08084841e-01]]
x= [  5.74181654e-01   6.44011849e+03   1.16073652e+03   6.91127353e-01
   3.22274403e-01   2.90281124e+03   5.88161958e-01   3.41367880e-01
   7.55204456e-01   5.08084841e-01]
     fun: -1274.8592956677317
   maxcv: 8.3266726846928772e-17
 message: 'Maximum number of function evaluations has been exceeded.'
    nfev: 1000
  status: 2
 success: False
       x: array([  7.94011045e+01,   6.43080806e+03,   7.21170754e+02,
        -8.32667268e-17,   3.24655178e+01,   2.91303530e+03,
         3.95923541e+00,   1.26710451e+02,   7.33402048e+00,
         2.84881446e+00])
-82.59000956544635 [[ -9.51866450e-01   8.38697463e-02   8.67996704e-01   0.00000000e+00
    0.00000000e+00]
 [  4.62211254e+03  -4.62275606e+03   0.00000000e+00   6.43518503e-01
    0.00000000e+00]
 [  7.83410975e-01   0.00000000e+00  -1.32656283e+00   2.17272465e-01
    3.25879386e-01]
 [  0.00000000e+00   9.06343131e-01   3.58030477e-01  -1.26437361e+00
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   1.12428009e-01   0.00000000e+00
   -1.12428009e-01]]
Inequality constraints incompatible    (Exit mode 4)
            Current function value: -1932.1916761250732
            Iterations: 25
            Function evaluations: 314
            Gradient evaluations: 25
     fun: -1932.1916761250732
     jac: array([ -7.79186472e+07,  -4.69091861e+07,  -4.69091859e+07,
        -4.69091861e+07,  -9.37225744e+07,  -1.72530690e+08,
        -8.62568783e+07,  -9.37225740e+07,  -6.50024414e-02,
        -9.06735762e+07,   0.00000000e+00])
 message: 'Inequality constraints incompatible'
    nfev: 314
     nit: 25
    njev: 25
  status: 4
 success: False
       x: array([  2.78696256e+02,   6.43421935e+03,  -3.98123191e-14,
         1.79885994e+02,   3.33000335e+02,   2.92612560e+03,
         1.58470668e+01,   2.08011337e+02,   3.92637131e+01,
        -1.11022302e-16])
20.291820543659554 [[ -1.00114729e+00   3.80618205e-02   9.63085473e-01   0.00000000e+00
    0.00000000e+00]
 [  5.68001382e-02  -6.93721904e-01   0.00000000e+00   6.36921766e-01
    0.00000000e+00]
 [  3.91225175e+03   0.00000000e+00  -3.91254095e+03   2.23487236e-01
    6.57170036e-02]
 [  0.00000000e+00   8.36963851e-01   4.68661911e-01  -1.30562576e+00
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   7.98806965e-01   0.00000000e+00
   -7.98806965e-01]]
[  5.75020352e-01   6.44012717e+03   1.20695765e+03   6.97562538e-01
   3.30108513e-01   2.90281341e+03   5.91420752e-01   3.50431311e-01
   7.58784761e-01   5.09209121e-01]
-1932.1916761250732